﻿using System;
using System.IO;
using System.Text;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace Silent.Data.Serialization
{
    public class XmlSerializationService : ISerializationService, ISerializationServiceGeneric
    {
        public void Serialize(Type type, object source, string filename)
        {
            using (var writer = new StreamWriter(filename))
            {
                var value = new XmlSerializer(type);
                value.Serialize(writer, source);
            }
        }
        public void Serialize(Type type, object source, Stream stream)
        {
            var value = new XmlSerializer(type);
            value.Serialize(stream, source);
        }

        public object Deserialize(Type type, string filename)
        {
            if (!File.Exists(filename))
                throw new FileNotFoundException("File specified was not found", filename);

            using (var reader = new StreamReader(filename))
            {
                var result = new XmlSerializer(type);
                return result.Deserialize(reader);
            }
        }
        public object Deserialize(Type type, Stream source)
        {
            var value = new XmlSerializer(type);
            return value.Deserialize(source);
        }
        public void Serialize<T>(T source, string filename)
        {
            Serialize(typeof (T), source, filename);
        }
        public void Serialize<T>(T source, Stream stream)
        {
            Serialize(typeof(T), source, stream);
        }
        public T Deserialize<T>(string filename)
        {
            return (T) Deserialize(typeof (T), filename);
        }
        public T Deserialize<T>(Stream source)
        {
            return (T) Deserialize(typeof (T), source);
        }
        public XElement Serialize(Type type, object source)
        {
            using (var stream = new MemoryStream())
            {
                using (var streamWriter = new StreamWriter(stream))
                {
                    var xmlSerializer = new XmlSerializer(type);
                    xmlSerializer.Serialize(streamWriter, source);
                    return XElement.Parse(Encoding.ASCII.GetString(stream.ToArray()));
                }
            }
        }
        public XElement Serialize<T>(T source)
        {
            return Serialize(typeof (T), source);
        }
        public object Deserialize(Type type, XElement element)
        {
            if (element == null)
                return null;

            using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(element.ToString())))
            {
                var xmlSerializer = new XmlSerializer(type);
                return xmlSerializer.Deserialize(stream);
            }
        }
        public T Deserialize<T>(XElement element)
        {
            return (T) Deserialize(typeof (T), element);
        }
    }
}